/**
 * 自定义bind实现
 * @param context   上下文this对象
 */
Function.prototype.myBind = function(context) {
  // 判断调用的对象是否是函数 context是this的指向，this是调用call的函数
  if (typeof this !== 'function') {
    throw new TypeError('Error');
  }
  // 判断context,如果为null 或者dundefined 则等于window
  // context = (typeof context === 'object' ? context : window);
  context = context || window;
  // this指向myBind的调用者，也就是函数
  const fn = this;
  // 获取bind中除了this指向的其他实参
  const args = [...arguments].slice(1);
  // 返回一个函数result
  const result = function() {
    // // 这个时候的arguments是指bind返回的函数传入的参数
    const resultArgs = [...arguments];
    // 判断this是否为函数的实例对象，
    if (this instanceof result) {
      // 通过new resutl 调用函数 则绑定实例对象
      fn.apply(this, args.concat(resultArgs));
    } else {
      // 否则普通调用绑定bind中的this指向  也就是context
      fn.apply(context, args.concat(resultArgs))
    }
  }
  // 将返回函数的 prototype赋值为调用函数的原型，构成原型链，result实例就可以继承调用函数的原型中的值
  result.prototype = Object.create(fn.prototype);
  return result;
};
// 测试用例
var value = 2;

var foo = {
  value: 1
};

function bar(name, age) {
  this.habit = 'shopping';
  console.log(this.value);
  console.log(name);
  console.log(age);
}

bar.prototype.friend = 'kevin';

var bindFoo = bar.myBind(foo, 'daisy');

var obj = new bindFoo('18');
// undefined
// daisy
// 18
console.log(obj.habit);
console.log(obj.friend);
// shopping
// kevin
bindFoo('18')
// 1
// daisy
// 18